#ifndef __UC_WIOTA_API_H__
#define __UC_WIOTA_API_H__

#include "rtdevice.h"

// WIoTa广播（包括普通广播、OTA和组播）单次发送的最大长度
#define UC_BC_MAX_LEN (1024)
// WIoTa单播单次发送的最大长度
#define UC_DL_MAX_LEN (310)
// WIoTa频点列表的最大个数
#define UC_FREQ_LIST_MAX_NUM (16)

/**
 * @brief WIoTa某些函数执行结果枚举
 *
 */
typedef enum
{
    UC_OP_SUCC = 0,       /**< 成功 */
    UC_OP_TIMEOUT = 1,    /**< 超时 */
    UC_OP_FAIL = 2,       /**< 失败 */
    UC_OP_MP_POOL = 3,    /**< AP内存池不足 */
    UC_OP_DROP_CLEAR = 4, /**< 终端掉线时仍有数据未发送，则返回该值 */
} uc_result_e;

/**
 * @brief WIoTa发送结果结构体
 *
 */
typedef struct
{
    unsigned int user_id; /**< IoTE的user id */
    unsigned int data_id; /**< 调用发送接口传入的para */
    unsigned int result;  /**< 发送结果 uc_result_e */
} uc_send_recv_t;

/**
 * @brief 单个频点信息结构体
 *
 */
typedef struct
{
    unsigned char freq_idx;  /**< 频点*/
    signed char snr;         /**< 频点对应的信噪比 */
    signed char rssi;        /**< 频点对应的信号强度 */
    unsigned char is_synced; /**< 该频点是否能同步上，为1表示能同步上，能同步上则说明有其他AP正在使用 */
} uc_scan_freq_t;

/**
 * @brief 扫频结果对应信息结构体
 *
 */
typedef struct
{
    uc_scan_freq_t *freq_info; /**< 频点信息 */
    unsigned short freq_num;   /**< 频点个数 */
    unsigned short result;     /**< 扫频结果 uc_result_e */
} uc_scan_recv_t;

/**
 * @brief 温度查询结果结构体
 *
 */
typedef struct
{
    signed char temp;     /**< AP8288芯片温度值，单位：摄氏度 */
    unsigned char result; /**< 温度查询结果，uc_result_e，温度查询只有在没有上下行任务时查询，如果有任务会返回失败 */
} uc_temp_recv_t;

/**
 * @brief sync paging执行结果结构体
 *
 */
typedef struct
{
    unsigned int user_id; /**< 执行sync paging完成的user id */
    unsigned int result;  /**< sync paging执行只有成功没有其他结果 */
} uc_paging_recv_t;

/**
 * @brief 发送sync paging信息结构体
 *
 */
typedef struct
{
    unsigned int user_id;          /**< 执行sync paging的user id */
    unsigned int fn_index;         /**< 通过sync paging ctrl消息接收回调（通过uc_wiota_register_sync_paging_callback注册）
                                        返回的IoTE第一次进入sync paging睡眠的帧号 */
    unsigned int detection_period; /**< IoTE的检测周期，和IoTE配置一致 */
    unsigned short send_round;     /**< 发送sync paging请求的轮数，理论上设置为1即可，如果遇到唤不醒的情况可适当增大 */
    unsigned short continue_fn;    /**< 单轮发送sync paging请求的帧数，理论上设置为1即可，设置为1表示只在周期帧发送，设置为2表示在
                                      周期帧前后各加1帧发送，为3表示前后各加2帧，以此类推，但最大值不能超过检测周期（detection_period）
                                      的一半，如果超过将被设为检测周期的一半 */
} uc_paging_info_t;

/**
 * @brief user id在帧结构的位置信息结构体
 *
 */
typedef struct
{
    unsigned char group_idx; /**< 在帧结构的group位置，常规配置下一般为0或1 */
    unsigned char burst_idx; /**< 在帧结构的burst位置，范围0~7 */
    unsigned char slot_idx;  /**< 在帧结构的slot位置，范围0~7 */
    unsigned char reserved;  /**< 对齐预留位 */
} uc_dev_pos_t;

/**
 * @brief WIoTA子网配置信息结构体，改结构体参数必须和IoTE一致，否则影响同步
 *
 */
typedef struct
{
    signed char power;           /**< AP发射功率，默认22dbm，最小0dbm，最大29dbm */
    unsigned char id_len;        /**< IoTE user id的长度，配置为0，1，2，3代表2，4，6，8字节，目前只支持4个字节的ID，即配置为1 */
    unsigned char pp;            /**< 固定为1，此值涉及同步灵敏度、传输效率等系统性能，暂时不提供修改 */
    unsigned char symbol_length; /**< 帧配置，取值0，1，2，3代表128，256，512，1024 */
    unsigned char dlul_ratio;    /**< 帧配置，该值代表一帧里面上下行group的比例，取值0，1代表1:1和1:2 */
    unsigned char bt_value;      /**< 该值和调制信号的滤波器带宽对应，值越大，信号带宽越大，取值0，1代表BT配置为1.2和BT配置为0.3，
                                      bt_value为0时，代表使用的是低阶MCS组，即低码率传输组。bt_value为1时，代表使用的是高MCS组，即高码率传输组 */
    unsigned char group_number;  /**< 帧配置，取值0，1，2，3分别代表一帧里包含1，2，4，8个上行group数量 */
    unsigned char spectrum_idx;  /**< 频谱序列号，默认为3，即470-510M */
    unsigned char old_subsys_v;  /**< 匹配老版本IoTE（v2.3及之前的版本）标志位，默认值为0，表示不匹配老版本，如果需要匹配老版本，将该值设为1 */
    unsigned char bitscb;        /**< 比特加扰标志位，默认值为1，表示开启比特加扰，为0表示关闭比特加扰, 建议开启 */
    unsigned char reserved[2];   /**< 对齐预留位 */
    unsigned int subsystem_id;   /**< 子系统id（子系统的识别码，终端IOTE如果要连接该子系统（AP），需要将config配置里的子系统ID参数配置成该ID）*/
} sub_system_config_t;

/**
 * @brief 黑名单链表结构体
 *
 */
typedef struct blacklist
{
    // TODO：是否按子帧添加，以提高查询效率
    rt_slist_t node;      /**< 黑名单链表节点 */
    unsigned int user_id; /**< 加入黑名单的user id */
} uc_blacklist_t;

/**
 * @brief paging tx低功耗配置信息结构体，发送唤醒信号
 *
 */
typedef struct
{
    unsigned char freq;          /**< 低功耗唤醒频点配置*/
    unsigned char spectrum_idx;  /**< 低功耗唤醒频谱配置 */
    unsigned char bandwidth;     /**< 低功耗唤带宽配置 */
    unsigned char symbol_length; /**< 低功耗唤帧结构符号长度配置 */
    unsigned short awaken_id;    /**< 低功唤醒ID */
    unsigned char mode;          /**< 默认为0，表示不开启唤醒ID扩展，为1表示开启ID扩展 */
    unsigned char reserved;      /**< 对齐预留位 */
    unsigned int send_time;      /**< 唤醒信号发送时间 */
} uc_lpm_tx_cfg_t, *uc_lpm_tx_cfg_p;

/**
 * @brief WIoTa子帧数据配置信息结构体，用于配置子帧的发送轮数和编码块大小
 *
 */
typedef struct
{
    unsigned char block_size;  /**< 编码块大小 */
    unsigned char send_round;  /**< 发送轮数 */
    unsigned char reserved[2]; /**< 对齐预留位 */
} uc_subf_cfg_t;

/**
 * @brief WIoTA协议栈log类型枚举
 *
 */
typedef enum
{
    UC_LOG_UART = 0, /**< 串口log，默认uart1 */
    UC_LOG_SPI = 1,  /**< SPI log 需要有Trace log工具配合抓取 */
} uc_log_type_e;

/**
 * @brief WIoTa广播发送模式枚举
 *
 */
typedef enum
{
    NORMAL_BROADCAST = 0, /**< 普通广播，固定子帧6发送，且每隔两帧发送一次，速度较慢，基本不会影响上行业务 */
    OTA_BROADCAST = 1,    /**< OTA广播，除子帧6外的所有下行子帧都可发送，速度较快，但如果一直发送可能影响上行任务 */
    INVALID_BROACAST
} uc_bc_mode_e;

/**
 * @brief WIoTa速率模式枚举
 *
 */
typedef enum
{
    UC_RATE_NORMAL = 0,
    UC_RATE_MID = 1,
    UC_RATE_HIGH = 2,
    UC_RATE_CRC_TYPE = 3,
} uc_data_rate_mode_e;

/**
 * @brief WIoTA速率等级枚举，速度等级越高，单包携带数据量越大，传输速度越快，UC_MCS_LEVEL_AUTO为自动MCS，0~7为固定MCS
 *        此外不同symbol_length下的相同MCS，携带的数据量亦有差距，具体请参考API文档
 *
 */
typedef enum
{
    UC_MCS_LEVEL_0 = 0,      /**< 速率为MCS0 */
    UC_MCS_LEVEL_1 = 1,      /**< 速率为MCS1 */
    UC_MCS_LEVEL_2 = 2,      /**< 速率为MCS2 */
    UC_MCS_LEVEL_3 = 3,      /**< 速率为MCS3 */
    UC_MCS_LEVEL_4 = 4,      /**< 速率为MCS4 */
    UC_MCS_LEVEL_5 = 5,      /**< 速率为MCS5 */
    UC_MCS_LEVEL_6 = 6,      /**< 速率为MCS6 */
    UC_MCS_LEVEL_7 = 7,      /**< 速率为MCS7 */
    UC_MCS_LEVEL_AUTO = 8,   /**< 下行自动MCS */
    UC_MCS_LEVEL_INVALID = 9 /**< 无效MCS */
} uc_mcs_level_e;

/**
 * @brief WIoTa uboot设置枚举，用于AP OTA升级设置使用
 *
 */
typedef enum
{
    UBOOT_SELECT_FLAG_SET = 0, /**< uboot菜单输出控制 */
    UBOOT_LOG_FLAG_SET = 1,    /**< uboot log输出口选择，uart0或uart1  */
    UBOOT_UART_FLAG_SET = 2,   /**< uboot串口log开关 */
    UBOOT_FILE_SIZE_SET = 3    /**< OTA文件大小设置 */
} set_uboot_e;

/**
 * @brief WIoTa授时状态
 *
 */
typedef enum
{
    TIME_SERVICE_NULL = 0,      /**< 未开启授时的状态 */
    TIME_SERVICE_START = 1,     /**< 授时开始的状态 */
    TIME_SERVICE_SUC = 2,       /**< 一次授时成功的状态 */
    TIME_SERVICE_FAIL = 3,      /**< 授时结果偏差过大无法完成对齐校验的状态 */
    TIME_SERVICE_INIT_END = 4,  /**< 初次开机经过授时完成帧头计算成功后的状态，通过次状态可判断授时是否成功 */
    TIME_SERVICE_ALIGN_END = 5, /**< 非初次开机，每隔固定时间进行帧头对齐校准成功的状态 */
    TIME_SERVICE_STOP = 6,      /**< 一次授时停止的状态 */
} time_service_state_e;

/**
 * @brief WIoTa授时类型枚举
 *
 */
typedef enum
{
    TIME_SERVICE_GNSS = 0,          /**< GPS授时，AP模组自带精度较高，开启后启动流程需要特殊处理 */
    TIME_SERVICE_1588_PROTOCOL = 1, /**< 需要外接1588协议授时，精度偏低，且依赖网络环境和路由配置，不推荐 */
    TIME_SERVICE_SYNC_ASSISTANT = 2 /**< 同步助手授时模式，精度最高，需要外接同步助手配套使用，使用简单插入即用，推荐 */
} time_service_type_e;

/**
 * @brief WIoTa上行数据包类型
 *
 */
typedef enum
{
    DATA_TYPE_ACCESS = 0,   /**< IoTE第一次上行接入（IoTE接入后离开连接态后再接入也定义为第一次接入）的消息类型，接入数据会携带4字节的user id */
    DATA_TYPE_ACTIVE = 1,   /**< IoTE接入后，在连接态时间内收到的消息，连接态消息不携带user id */
    DATA_TYPE_SUBF_DATA = 2 /**< 连续子帧数据，语音数据专用数据类型 */
} uc_recv_data_type_e;

typedef struct
{
    unsigned int user_id;          /**< IoTE的user id */
    uc_recv_data_type_e data_type; /**< 接收到的数据类型 */
    unsigned char *data;           /**< 接收到的数据 */
    unsigned short data_len;       /**< 接收到的数据长度 */
    signed char rssi;              /**< 信号强度 */
    unsigned char delay;           /**< 接入延迟 */
    unsigned char fn_cnt;          /**< 语音数据的接收计数， data_type为DATA_TYPE_SUBF_DATA时有效*/
    unsigned char group_idx;       /**< 在帧结构的group位置，常规配置下一般为0或1 */
    unsigned char burst_idx;       /**< 在帧结构的burst位置，范围0~7 */
    unsigned char slot_idx;        /**< 在帧结构的slot位置，范围0~7 */
    unsigned int frame_num;        /**< 接收到数据时的帧号 */
} uc_recv_detail_t;

typedef struct
{
    unsigned int ts_state;    /**< 授时状态，time_service_state_e */
    unsigned int frame_head;  /**< WIoTa帧头*/
    int frame_head_offset;    /**< WIoTa帧头偏移，用于校验授时结果 */
    unsigned int cur_time_s;  /**< 当前世界时间的时间戳整秒部分 */
    unsigned int cur_time_us; /**< 当前世界时间的时间戳微秒部分，这个时间是从AP传到主控，传输过程中仍会有精度丢失 */
    int pos_x;                /**< 定位坐标x，授时的基础是先定位，因此也可以获取到当前的定位信息 */
    int pos_y;                /**< 定位坐标y */
    int pos_z;                /**< 定位坐标z */
    float longitude;          /**< 经度 */
    float latitude;           /**< 纬度 */
    float altitude;           /**< 海拔 */
} uc_ts_info_t;

//{WIoTa回调函数定义，通常用于非阻塞调用接口时，返回结果
// 发送结果回调函数
typedef void (*uc_send_callback)(uc_send_recv_t *result);
// 扫频结果回调函数
typedef void (*uc_scan_callback)(uc_scan_recv_t *result);
// 温度查询结果回调函数
typedef void (*uc_temp_callback)(uc_temp_recv_t *result);
// sync paging结果回调函数
typedef void (*uc_paging_callback)(uc_paging_recv_t *result);
// sync paging ctrl消息接收回调，IotE进入sync paging睡眠模式前，会发送一个ctrl消息给AP，AP收到该ctrl消息后会调用该回调通知应用层，该IoTE是哪一帧（fn_index）睡眠的，
// 应用层需记录fn_index的值，当需要唤醒该IoTE时，调用uc_wiota_sync_paging接口将fn_Index传给AP以唤醒该IoTE
typedef void (*uc_paging_ctrl_callback)(unsigned int user_id, unsigned char burst_idx, unsigned int fn_index);
// 授时状态信息回调
typedef void (*uc_time_service_callback)(time_service_state_e state);
// 授时状态信息回调，由于现在需要传输状态信息以外的其他信息，故改动了原来的回调函数，增加了授时信息
typedef void (*uc_time_service_info_callback)(uc_ts_info_t *ts_info);
// IoTE离开连接态，掉线提示回调函数
typedef void (*uc_iote_drop)(unsigned int user_id);
// IoTE上行数据接收回调函数
typedef void (*uc_recv)(unsigned int user_id, unsigned char *recv_data, unsigned short data_len, uc_recv_data_type_e data_type);
// IoTE上行数据接收回调函数，更加详细
typedef void (*uc_recv_detail)(uc_recv_detail_t *recv_detail);
// AP帧号刷新回调函数
typedef void (*uc_fn_refresh_callback)(unsigned int frame_num);
//}

/**
 * @brief 定帧收发结构体
 *
 */
typedef struct
{
    // recv
    unsigned int user_id;       /**< IoTE的user id */
    unsigned int start_recv_fn; /**< 开始接收的帧号 */
    unsigned char recv_fns;     /**< 接收任务的帧数 */
    // send，data_len为0时表示不发送数据
    unsigned char send_fns;    /**< 发送任务的帧数 */
    unsigned short data_len;   /**< 数据长度 */
    unsigned char *data;       /**< 数据 */
    uc_send_callback callback; /**< 发送结果回调函数 */
    void *para;                /**< 发送结果回调函数参数，一般为数据地址 */
} recv_send_by_fn_t;

/**
 * @brief 获取WIoTa的版本号，构建时间等信息
 *
 * @param wiota_version_8088 AP8088的协议栈版本
 * @param git_info_8088      AP8088的git最新一条的信息
 * @param make_time_8088     AP8088的协议栈版本构建时间
 * @param wiota_version_8288 AP8288的协议栈版本
 * @param git_info_8288      AP8288的git最新一条的信息
 * @param make_time_8288     AP8288的协议栈版本构建时间
 * @param cce_version        AP CCE版本
 * @return int               0表示成功，非0表示失败
 */
int uc_wiota_get_version(char *wiota_version_8088, char *git_info_8088, char *make_time_8088,
                         char *wiota_version_8288, char *git_info_8288, char *make_time_8288,
                         int *cce_version);

/**
 * @brief WIoTa协议栈初始化接口
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_init(void);

/**
 * @brief WIoTa协议栈运行接口
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_run(void);

/**
 * @brief WIoTa协议栈退出接口
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_exit(void);

/**
 * @brief 使能AP电源
 *
 */
void uc_wiota_power_on(void);

/**
 * @brief 关闭AP电源
 *
 */
void uc_wiota_power_off(void);

/**
 * @brief AP模组重启接口，软复位
 *
 */
void uc_wiota_reboot(void);

/**
 * @brief 使能同步助手电源
 *
 */
void uc_wiota_sync_assistant_power_on(void);

/**
 * @brief 关闭同步助手电源
 *
 */
void uc_wiota_sync_assistant_power_off(void);

/**
 * @brief 同步助手模组重启
 *
 */
void uc_wiota_sync_assistant_reboot(void);

/**
 * @brief 注册IoTE掉线提示回调函数，当IoTE接入后，在连接态时间内未在和AP交互，AP会将该IoTE踢掉，称为IoTE掉线
 *
 * @param callback 掉线提示回调函数指针
 */
void uc_wiota_register_iote_dropped_callback(uc_iote_drop callback);

/**
 * @brief 注册IoTE上行数据接收回调函数，当AP收到IoTE上行数据并收完后，触发回调，将接收到的数据传给应用层
 *
 * @param callback 上行数据接收回调函数指针
 */
void uc_wiota_register_recv_data_callback(uc_recv callback);

/**
 * @brief 注册IoTE上行数据接收回调函数，当AP收到IoTE上行数据并收完后，触发回调，将接收到的数据传给应用层，
 *        相较于uc_wiota_register_recv_data_callback上报信息更加详细，且两个回调只会生效一个，后者生效
 *
 * @param callback 上行数据接收回调函数指针
 */
void uc_wiota_register_recv_data_detail_callback(uc_recv_detail callback);

/**
 * @brief 设置WIoTa子网配置
 *
 * @param config WIoTa子网配置结构体指针
 * @return int   0表示成功，非0表示失败
 */
int uc_wiota_set_system_config(sub_system_config_t *config);

/**
 * @brief 获取WIoTa子网配置
 *
 * @param config WIoTa子网配置结构体指针
 * @return int   0表示成功，非0表示失败
 */
int uc_wiota_get_system_config(sub_system_config_t *config);

/**
 * @brief 设置WIoTa连接态超时时间，IoTE接入到超时时间结束，称为连接态，在连接态期间收到的消息称为连接态消息，只要IoTE和AP有交互就会重置连接态时间，
 *        超过连接态时间未交互，IoTE掉线
 *
 * @param active_s 连接态超时时间，单位：秒
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_set_active_time(unsigned int active_s);

/**
 * @brief 获取WIoTa连接态超时时间
 *
 * @return int 连接态超时时间
 */
unsigned int uc_wiota_get_active_time(void);

/**
 * @brief 单独设置AP发送功率接口，功率支持热设置（AP运行中也可设置）
 *
 * @param power    AP发射功率，范围0~29dbm
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_set_ap_tx_power(signed char power);

/**
 * @brief 设置WIoTa工作频点，不支持热配置
 *
 * @param freq_idx 频点，范围：0~200
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_set_freq_info(unsigned char freq_idx);

/**
 * @brief 获取WIoTa工作频点
 *
 * @return unsigned char 0~200表示成功，0xFF表示失败
 */
unsigned char uc_wiota_get_freq_info(void);

/**
 * @brief 设置WIoTa跳频频点，WIoTa支持简单的跳频，即在两个频点上工作
 *
 * @param hopping_freq 跳频频点，不要和工作频点一样，范围：0~200
 * @return int         0表示成功，非0表示失败
 */
int uc_wiota_set_hopping_freq(unsigned char hopping_freq);

/**
 * @brief 设置跳频模式接口，设置了跳频频点还需设置跳频模式，以指定在工作频点和跳频频点工作的帧数
 *
 * @param ori_freq_frame     在原频点（即工作频点）工作的帧数
 * @param hopping_freq_frame 在跳频频点工作的帧数
 * @return int               0表示成功，非0表示失败
 */
int uc_wiota_set_hopping_mode(unsigned char ori_freq_frame, unsigned char hopping_freq_frame);

/**
 * @brief 设置WIoTa最大的连接态终端数量，dlul_ratio为0时默认为72个，dlul_ratio为1时默认为144个，如果有超过该值的需求，在wiota_run之前调用设置
 *
 * @param max_iote_num 最大的连接态终端数量，最好为8的帧数倍，范围1~800
 * @return int         0表示成功，非0表示失败
 */
int uc_wiota_set_max_num_of_active_iote(unsigned short max_iote_num);

/**
 * @brief 获取WIoTa最大的连接态终端数量
 *
 * @return unsigned short 最大的连接态终端数量，0表示查询失败
 */
unsigned short uc_wiota_get_max_num_of_active_iote(void);

/**
 * @brief 设置WIoTa速率模式和对应模式的值
 *        第一种模式，是设置下行单播速率，设置值为uc_mcs_level_e
 *        在第一种模式的基础上，在系统配置中dlul_ratio为1:2时，才能打开第二种模式，打开该模式能够提高该帧结构情况下两倍速率，默认第二种模式关闭
 *        在第一种模式的基础上，打开第三种模式，能够提升8*(1 << group_number)倍单终端的速率，但是会影响网络中其他终端的上行，建议在大数据量快速传输需求时使用
 *
 * @param rate_mode  WIoTa速率模式，对应枚举uc_data_rate_mode_e
 * @param rate_value normal模式取值为uc_mcs_level_e，且在不同symbol_length下支持的速率最大值亦有限制，symbol_length为0，1，2，3时对应的最大速率分别为
 *                   MCS4，MCS6，MCS7和MCS7
 *                   mid模式取值为0或1，表示开启或关闭中速模式，且只能在dlul_ratio为1:2时开启，1:1不支持
 *                   high模式取值为0或1~UC_DL_MAX_LEN，表示关闭或发送长度大于设定值时开启，且只支持dlul_ratio为1:1的配置，1:2不支持
 *                   crc_type表示基带crc的长度，默认为4字节，当crc_type为1时，表示1字节的crc，此种情况下单帧数据量会多三个字节，语音专用其他模式不用开启
 * @return int       0表示成功，非0表示失败
 */
int uc_wiota_set_data_rate(uc_data_rate_mode_e rate_mode, unsigned int rate_value);

/**
 * @brief 获取WIoTa速率模式的值
 *
 * @param rate_mode     WIoTa速率模式
 * @return unsigned int 参考设置接口的rate_value
 */
unsigned int uc_wiota_get_data_rate_value(uc_data_rate_mode_e rate_mode);

/**
 * @brief 设置WIoTa广播发送速率
 *
 * @param bc_mcs 广播发送速率，只能为固定MCS，不能为自动MCS，范围：MCS0~MCS6
 *               在不同symbol_length下支持的速率最大值亦有限制，symbol_length为0，1，2，3时对应的最大速率分别为MCS4，MCS6，MCS6和MCS5
 * @return int   0表示成功，非0表示失败
 */
int uc_wiota_set_broadcast_mcs(uc_mcs_level_e bc_mcs);

/**
 * @brief 获取WIoTa广播发送速率
 *
 * @return uc_mcs_level_e 广播发送速率
 */
uc_mcs_level_e uc_wiota_get_broadcast_mcs(void);

/**
 * @brief 设置WIoTa广播帧发送周期，默认11帧发送一次，广播帧用于发送一些控制信息和同步帧号，非特殊用途（如配合IoTE睡眠起来后发送数据）不建议修改
 *
 * @param bc_fn_cycle 广播帧发送周期，范围1~11，注意设置为1时，相当于每帧都发广播帧，会导致子帧6无法发送其他下行短消息
 * @return int        0表示成功，非0表示失败
 */
int uc_wiota_set_broadcast_fn_cycle(unsigned char bc_fn_cycle);

/**
 * @brief 获取WIoTa广播帧发送周期
 *
 * @return unsigned char 广播帧发送周期
 */
unsigned char uc_wiota_get_broadcast_fn_cycle(void);

/**
 * @brief 设置广播发轮数，默认三轮，非特殊需求不建议更改
 *
 * @param round 发送轮数
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_set_broadcast_send_round(unsigned char round);

/**
 * @brief 获取广播发轮数
 *
 * @return unsigned char 发送轮数
 */
unsigned char uc_wiota_get_broadcast_send_round(void);

/**
 * @brief 获取当前配置的WIoTa帧结构的单帧帧长
 *
 * @return int 帧长，单位：微妙
 */
unsigned int uc_wiota_get_frame_len(void);

/**
 * @brief 获取AP当前帧号
 *
 * @return unsigned int 帧号
 */
unsigned int uc_wiota_get_frame_num(void);

/**
 * @brief 获取AP8288运行状态
 *
 * @return int 0表示异常，1表示正常，其他表示获取失败
 */
int uc_wiota_get_ap8288_state(void);

/**
 * @brief AP状态检查，将网关定时检测crc和ap8288状态合并了，且用单独的共享内存存储该信息
 *
 * @return int 0表示异常，1表示正常
 */
int uc_wiota_check_state(void);

/**
 * @brief 清0AP中断计数
 *
 */
void uc_wiota_isr_cnt_clear(void);

/**
 * @brief 设置WIota发送时携带CRC校验，该接口设置的状态应该和IoTE同步，否则会造成数据接收错误，默认为发送长度大于100字节是添加CRC，该接口限制对所有下行
 *        生效（广播、OTA、组播和单播）
 *
 * @param crc_limit 为0表示关闭CRC，不管数据多长都不添加CRC；大于等于1时，表示发送长度大于设定值时添加CRC，如果要求所有长度数据都添加CRC，设置为1即可
 * @return int      0表示成功，非0表示失败
 */
int uc_wiota_set_crc(unsigned short crc_limit);

/**
 * @brief 获取当前的CRC限制值
 *
 * @return unsigned short 0~UC_BC_MAX_LEN表示成功，0xFFFF表示失败
 */
unsigned short uc_wiota_get_crc(void);

/**
 * @brief 获取黑名单并返回黑名单个数
 *
 * @param blacklist_num   黑名单个数
 * @return uc_blacklist_t 黑名单链表头，RT_NULL表示获取失败
 */
uc_blacklist_t *uc_wiota_get_blacklist(unsigned short *blacklist_num);

/**
 * @brief 添加一组user id到黑名单
 *
 * @param user_id     要添加的黑名单id数组首地址
 * @param user_id_num 要添加的黑名单id个数
 * @return int        0表示成功，非0表示失败
 */
int uc_wiota_add_iote_to_blacklist(unsigned int *user_id, unsigned short user_id_num);

/**
 * @brief 将一组user id从黑名单中移除
 *
 * @param user_id     要移除的黑名单id数组首地址
 * @param user_id_num 要移除的黑名单id个数
 * @return int        0表示成功，非0表示失败
 */
int uc_wiota_remove_iote_from_blacklist(unsigned int *user_id, unsigned short user_id_num);

/**
 * @brief WIoTa协议栈log开关，默认开启串口log，SPI log需要Trace log工具配合才能抓取
 *
 * @param log_type WIoTa协议栈log类型，串口log或SPI log
 * @param is_open  1表示开启log，0表示关闭log
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_log_switch(uc_log_type_e log_type, unsigned char is_open);

/**
 * @brief WIoTa广播（普通广播和OTA）发送接口
 *
 * @param send_data     要发送的广播数据指针
 * @param send_data_len 要发送的广播数据长度
 * @param mode          广播模式，普通广播或OTA
 * @param timeout       广播发送超时时间，该时间跟帧结构配置、业务类型、数据量和广播速率相关，如果不好把控，建议往大了设
 * @param callback      发送结果回调，传入RT_NULL时表示阻塞发送，非RT_NULL时表示非阻塞发送
 * @param para          用户自定义参数，该参数会在发送结果回调时传回来，一般传入发送数据的地址，用于知晓每段数据的发送结果
 * @return uc_result_e  成功或超时，广播没有ACK理论上不会有失败
 */
uc_result_e uc_wiota_send_broadcast_data(unsigned char *send_data,
                                         unsigned short send_data_len,
                                         uc_bc_mode_e mode,
                                         signed int timeout,
                                         uc_send_callback callback,
                                         void *para);

/**
 * @brief 设置WIoTa组播id，最多支持设置8个组播id，该id要和IoTE设置的组播接收id一致
 *
 * @param multicast_id 要设置的一组组播id首地址
 * @param id_num       要设置的组播id个数
 * @return int         0表示成功，非0表示失败
 */
int uc_wiota_set_multicast_id(unsigned int *multicast_id, unsigned int id_num);

/**
 * @brief 删除一组WIoTa组播id
 *
 * @param multicast_id 要删除的一组组播id首地址
 * @param id_num       要删除的组播id个数
 * @return int         0表示成功，非0表示失败
 */
int uc_wiota_del_multicast_id(unsigned int *multicast_id, unsigned int id_num);

/**
 * @brief WIoTa组播发送接口
 *
 * @param send_data     要发送的组播数据指针
 * @param send_data_len 要发送的组播数据长度
 * @param multicast_id  组播id，该id必须先通过设置组播id接口设置，否则会返回失败
 * @param timeout       组播发送超时时间，该时间跟帧结构配置、业务类型、数据量和广播速率相关，如果不好把控，建议往大了设
 * @param callback      发送结果回调，传入RT_NULL时表示阻塞发送，非RT_NULL时表示非阻塞发送
 * @param para          用户自定义参数，该参数会在发送结果回调时传回来，一般传入发送数据的地址，用于知晓每段数据的发送结果
 * @return uc_result_e  成功或超时，组播没有ACK理论上不会有失败，除非组播id未先设置
 */
uc_result_e uc_wiota_send_multicast_data(unsigned char *send_data,
                                         unsigned short send_data_len,
                                         unsigned int multicast_id,
                                         signed int timeout,
                                         uc_send_callback callback,
                                         void *para);

/**
 * @brief WIoTa单播发送接口
 *
 * @param send_data     要发送的单播数据指针
 * @param send_data_len 要发送的但播数据长度
 * @param user_id       要发送给某个IoTE的user id，该IoTE必须先和AP保持同步状态，否则会发送失败
 * @param timeout       单播发送超时时间，该时间跟帧结构配置、业务类型、数据量和广播速率相关，如果不好把控，建议往大了设
 * @param callback      发送结果回调，传入RT_NULL时表示阻塞发送，非RT_NULL时表示非阻塞发送
 * @param para          用户自定义参数，该参数会在发送结果回调时传回来，一般传入发送数据的地址，用于知晓每段数据的发送结果
 * @return uc_result_e  成功、超时或失败
 */
uc_result_e uc_wiota_send_data(unsigned char *send_data,
                               unsigned short send_data_len,
                               unsigned int user_id,
                               signed int timeout,
                               uc_send_callback callback,
                               void *para);

/**
 * @brief WIoTa顺序单播业务发送接口
 *
 * @param send_data      要发送的单播数据指针
 * @param send_data_len  要发送的但播数据长度
 * @param user_id        要发送给某个IoTE的user id，该IoTE必须先和AP保持同步状态，否则会发送失败
 * @param timeout        单播发送超时时间，该时间跟帧结构配置、业务类型、数据量和广播速率相关，如果不好把控，建议往大了设
 * @param order_business 顺序业务标识，为0时和普通单播业务相同，为1时表示该业务为顺序业务，会等待之前的业务终端掉线后再发送
 * @param callback       发送结果回调，传入RT_NULL时表示阻塞发送，非RT_NULL时表示非阻塞发送
 * @param para           用户自定义参数，该参数会在发送结果回调时传回来，一般传入发送数据的地址，用于知晓每段数据的发送结果
 * @return uc_result_e   成功、超时或失败
 */
uc_result_e uc_wiota_send_data_order(unsigned char *send_data,
                                     unsigned short send_data_len,
                                     unsigned int user_id,
                                     signed int timeout,
                                     unsigned int order_business,
                                     uc_send_callback callback,
                                     void *para);

/**
 * @brief WIoTa频点扫描接口，用于扫描一组频点，返回每个频点的频点信息
 *
 * @param freq           要扫描的一组频点数组的首地址
 * @param freq_nu        要扫描的一组频点个数
 * @param scan_type      扫频类型，0为普通扫描，执行慢，但结果更准确；1为快速扫描，执行快，但结果相对较差
 * @param timeout        扫频超时，建议1min以上
 * @param callback       扫频结果回调，传入RT_NULL时表示阻塞调用，非RT_NULL时表示非阻塞调用，一般都用阻塞方式
 * @param scan_result    扫频结果，包含了每个频点的信息
 * @return uc_result_e   成功、超时或失败
 */
uc_result_e uc_wiota_scan_freq(unsigned char *freq,
                               unsigned char freq_num,
                               unsigned char scan_type,
                               signed int timeout,
                               uc_scan_callback callback,
                               uc_scan_recv_t *scan_result);

/**
 * @brief 读取AP模组上AP8288的芯片温度（即基带温度），只有在没有上下行任务时才能读取，否则会直接返回失败
 *
 * @param callback  温度查询回调函数，传入RT_NULL时表示阻塞调用，非RT_NULL时表示非阻塞调用
 * @param read_temp 读取到的温度结果
 * @param timeout   读取超时时间
 * @return int      0表示成功，非0表示失败
 */
int uc_wiota_read_temperature(uc_temp_callback callback, uc_temp_recv_t *read_temp, signed int timeout);

/**
 * @brief 查询user id在帧结构的位置，id管理实现IoTE位置平铺的关键函数
 *
 * @param user_id        要查询的一组user id数组的首地址
 * @param user_id_num    要查询的一组user id个数
 * @return uc_dev_pos_t* 位置信息结构体指针，需要调用者手动释放
 */
uc_dev_pos_t *uc_wiota_query_dev_pos_by_userid(unsigned int *user_id, unsigned int user_id_num);

//{以下为AP帧边界同步相关接口，主要用于同一区域范围内的多个AP之间的帧边界同步校准，解决多AP之间上下行的影响
/**
 * @brief 注册授时信息回调函数，当授时状态发生变化时，触发回调，将状态传给应用层
 *
 * @param callback
 */
void uc_wiota_register_time_service_state_callback(uc_time_service_callback callback);

/**
 * @brief 注册授时信息回调函数，当授时状态发生变化时，触发回调，将状态传给应用层，上报信息更多
 *
 * @param callback
 */
void uc_wiota_register_time_service_info_callback(uc_time_service_info_callback callback);

/**
 * @brief 开启或关闭WIoTa帧边界校准功能，默认关闭，前提是必须开启一种授时方式
 *
 * @param is_open 开关标志，0表示关闭，1表示开启
 * @return int    0表示成功，非0表示失败
 */
int uc_wiota_set_frame_boundary_align_func(unsigned char is_open);

/**
 * @brief 根据需求开启或关闭一种授时模式，只可同时开启一种模式，最新的网关将采用同步助手的模式
 *
 * @param type    授时模式time_service_type_e
 * @param is_open 开关标识，0表示关闭，1表示开启
 * @return int    0表示成功，非0表示失败
 */
int uc_wiota_set_time_service_func(time_service_type_e type, unsigned char is_open);

/**
 * @brief 设置授时周期，默认15分钟授时一次，范围5~60分钟
 *
 * @param cycle_min 授时周期，单位分钟
 * @return int      0表示成功，非0表示失败
 */
int uc_wiota_set_time_service_cycle(unsigned char cycle_min);

/**
 * @brief 获取授时模式开关状态
 *
 * @param func_gnss GPS授时模式开关状态
 * @param func_1588 1588协议授时模式开关状态
 * @param func_sync 同步助手授时模式开关状态
 * @return int      0表示成功，非0表示失败
 */
int uc_wiota_get_time_service_func(unsigned char *func_gnss, unsigned char *func_1588, unsigned char *func_sync);

/**
 * @brief 启动同步授时，需要设置一种授时方式
 *
 * @return int    0表示成功，非0表示失败
 */
int uc_wiota_time_service_start(void);

/**
 * @brief 停止同步授时，一般情况下，开启后无需停止
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_time_service_stop(void);

/**
 * @brief 同步1588授时时间到AP模组，1588授时模式使用，由网关1588授时模块调用
 *
 * @param sec  时钟源的整秒部分
 * @param usec 时钟源的微秒部分
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_1588_time_sync(unsigned int sec, unsigned int usec);

/**
 * @brief 开启或关闭同步助手的秒脉冲，可用于测试和GPS秒脉冲是否同步，验证同步时间精度，需要开启授时模式为同步助手模式，验证完后建议关闭
 *
 * @param is_open 同步助手的秒脉冲开关标识，0表示关闭，1表示开启
 * @return int    0表示成功，非0表示失败
 */
int uc_wiota_set_sync_assistant_pps(unsigned char is_open);

/**
 * @brief 获取同步助手的秒脉冲开关标识
 *
 * @return unsigned char 同步助手的秒脉冲开关标识
 */
unsigned char uc_wiota_get_sync_assistant_pps(void);
//}授时相关接口结束

//{以下为AP远程唤醒进入低功耗睡眠的IoTE相关的接口，有两种方式，一种为发送paging tx单音信号，一种为发送sync paging控制消息
/**
 * @brief paging tx唤醒配置，该方式为发送连续唤醒信号，进入该模式低功耗的IoTE的基带会周期性检测这个信号，当检测到后实现唤醒，故该配置需要和要唤醒的IoTE配置一致
 *
 * @param config paging tx低功耗唤醒配置
 * @return int   0表示成功，非0表示失败
 */
int uc_wiota_set_paging_tx_cfg(uc_lpm_tx_cfg_t *config);

/**
 * @brief 获取paging tx唤醒配置
 *
 * @return uc_lpm_tx_cfg_t* 配置结构体指针
 */
uc_lpm_tx_cfg_t *uc_wiota_get_paging_tx_cfg(void);

/**
 * @brief 开启paging tx唤醒，设置完配置后，调用该接口发送连续唤醒信号，实现唤醒
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_start_paging_tx(void);

/**
 * @brief 注册WIoTa sync paging 控制消息接收回调函数
 *
 * @param callback sync paging 控制消息接收回调函数指针
 */
void uc_wiota_register_sync_paging_callback(uc_paging_ctrl_callback callback);

/**
 * @brief 发送sync paging请求唤醒进入sync paging模式睡眠的IoTE，前提会必须收到fn_index，否则会导致唤醒失败
 *
 * @param paging_info  sync paging信息结构体指针
 * @param callback     sync paging执行结果回调，传入RT_NULL时表示阻塞调用，非RT_NULL时表示非阻塞调用，建议非阻塞调用
 * @return uc_result_e sync paging执行结果，只有成功
 */
uc_result_e uc_wiota_sync_paging(uc_paging_info_t *paging_info, uc_paging_callback callback);

/**
 * @brief 获取某帧结构位置上正在进行sync paging的IoTE个数
 *
 * @param group_idx      帧结构group位置
 * @param subframe_idx   帧结构子帧位置
 * @return unsigned char 正在进行sync paging的IoTE个数
 */
unsigned char uc_wiota_get_sync_paging_num(unsigned char group_idx, unsigned char subframe_idx);
//}远程唤醒API结束

/**
 * @brief AP单独发送单音信号
 *
 * @param is_open 开启发送单音信号
 * @return int    0表示成功，非0表示失败
 */
int uc_wiota_set_single_tone(unsigned int is_open);

/**
 * @brief 设置协议层单播重发次数
 *
 * @param resend_times
 * @return int
 */
int uc_wiota_set_sm_resend_times(unsigned char resend_times);

/**
 * @brief AP帧号刷新回调注册
 *
 * @param callback 回调函数指针
 */
void uc_wiota_register_fn_refresh_callback(uc_fn_refresh_callback callback);

/**
 * @brief 让终端主动处于连接态并根据参数接收和发送短消息
 *
 * @param rs_fn           定帧收发结构体指针
 * @return uc_result_e    0表示成功，非0表示失败
 */
uc_result_e uc_wiota_recv_send_sm_by_fn(recv_send_by_fn_t *rs_fn);

/**
 * @brief 设置子帧模式配置，协议栈根据此配置，发送和编码子帧数据
 *
 * @param subf_cfg   子帧模式配置
 * @return int       0表示成功，非0表示失败
 */
int uc_wiota_set_subframe_mode_cfg(uc_subf_cfg_t *subf_cfg);

/**
 * @brief 设置上行子帧连续接收模式，用于语音接收，可根据接收数据类型来判断是否为子帧数据
 *
 * @param subf_mode  是否打开标志，0表示关闭，1表示一帧一包语音数据，2表示一帧两包语音数据
 * @param user_id    要打开子帧连续接收模式的终端ID
 * @param rach_delay 接入延迟
 * @return int       0表示成功，非0表示失败
 */
int uc_wiota_set_ul_subframe_mode(unsigned char subf_mode, unsigned int user_id, unsigned char rach_delay);

/**
 * @brief 添加下行子帧数据，语音传输专用，除子帧6以外的所有下行子帧都可以发，且只需控制一次广播帧开始，发送数据大小为当前mcs的最大且为语音编码块的整数倍
 *
 * @param data      要发送的下行子帧数据指针
 * @param data_len  要发送的下行子帧数据长度
 * @return fn       上行子帧数据接收的帧号，下行回填
 * @return int      0表示成功，非0表示失败
 */
int uc_wiota_add_dl_subframe_data(unsigned char *data, unsigned char data_len, unsigned char fn);

/**
 * @brief 设置aagc
 *
 * @param aagc_idx  aagc索引
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_set_aagc_idx(unsigned char aagc_idx);

/**
 * @brief 开启bnack冲突解决功能，开启该功能后当同一子帧有多个终端同时传输时，竞争接入的终端会优先执行，竞争失败的终端会自动回避，能极大的提高多终端发送的成功率
 *
 * @param is_open  开启标志，0表示关闭，1表示开启
 * @return int     0表示成功，非0表示失败
 */
int uc_wiota_set_bnack_func(unsigned char is_open);

/**
 * @brief AT客户端初始化
 *
 * @return int 0表示成功，非0表示失败
 */
int uc_wiota_at_client_init(void);

/**
 * @brief AT通讯连接测试接口
 *
 * @param wait_timeout 等待超时时间
 * @return int         0表示成功，非0表示失败
 */
int uc_wiota_at_client_connect(unsigned int wait_timeout);

/**
 * @brief 网关和AP使用SPI通信初始化
 *
 */
void uc_wiota_spi_com_init(void);

/**
 * @brief 网关和AP使用SPI通信反初始化
 *
 */
void uc_wiota_spi_com_deinit(void);

#endif /* __UC_WIOTA_API_H__ */
